#include "message.h"
#include "book.h"


bool_t xdr_char_tab (XDR * xdr, char* str, int size)
{
        bool_t b = TRUE;
        int i;
        
        // Encodage
        if (xdr->x_op == XDR_ENCODE || xdr->x_op == XDR_DECODE)
        {
                for (i=0; i<size; i++)
                {
                        b = b && xdr_char(xdr, &(str[i]));
                }               
        }
        
        return b;
}

bool_t xdr_message (XDR * xdr, Message * msg)
{
        bool_t b;
        int i;
        
        // Décodage et encodage
        if (xdr->x_op == XDR_ENCODE || xdr->x_op == XDR_DECODE)
        {
        
                b = xdr_int(xdr, &(msg->timestamp)) &&
                    xdr_int(xdr, &(msg->type)) && 
                    xdr_char_tab(xdr, msg->ipSender,SIZEIP) && 
                    xdr_char_tab(xdr, msg->ipReceiver,SIZEIP) && 
                    xdr_char_tab(xdr, msg->nameSender,SIZENAME) &&      
                    xdr_char_tab(xdr, msg->nameReceiver,SIZENAME) && 
                    xdr_int(xdr, &(msg->size));
                    
                if (b == FALSE)
                {
                        return FALSE;
                }
                
                // Allocation dynamique du message lors du décodage
                if (xdr->x_op == XDR_DECODE)
                {
                        msg->message = (char*) malloc(msg->size * sizeof(char));
                }
                
                for (i=0; i<msg->size; i++)
                {
                        b = b && xdr_char(xdr, &((msg->message)[i]));
                }
        }
        
        return b;
}

bool_t isAlreadyReceived (Message * msg)
{
        bool_t b = FALSE;
        
        MessageReceivedList tmp = msgReceived;
          
        if (tmp != NULL)        
        {       	        	
        	do
        	{        	
				  	if (tmp->timestamp == msg->timestamp && strcmp(tmp->ipSender, msg->ipSender) == 0)     	
				  	{
				  		b = TRUE;
				  	}
		      		
		      	tmp = tmp->next;
        	}
        	while (tmp != NULL && b == FALSE);
		}
		
        return b;
}


void addMsgReceived (Message msg)               // add the message in MessageReceived
{
		MessageReceivedList tmp = malloc(sizeof(struct MRL));
		tmp->timestamp = msg.timestamp;
		strcpy(tmp->ipSender, msg.ipSender);
		tmp->next    = msgReceived;
		
		msgReceived = tmp;
}

void printMsgReceived ()
{        
        MessageReceivedList tmp = msgReceived;
          
        if (tmp != NULL)        
        {       	        	
        	do
        	{     
        	
        		printf("message : %d %s\n",  	tmp->timestamp, tmp->ipSender);
		      	tmp = tmp->next;
        	}
        	while (tmp != NULL);
		}
		else
		{
			printf("\n* Aucun message reçu\n");
			}
}

Message* newMessage()
{
	Message * m = malloc(sizeof(Message));
	return m;
}


void send_message_all(char * message, int type)
{
        int i, time_s;
        
        /* Sending "CONNECT" to all contacts */
        Message * msg;
        
        /* Timestamp */
        struct timeval tv;
        gettimeofday(&tv,NULL);
        time_s = tv.tv_sec;
        
        /* For each contact ... */
        for (i=0; i<adressBook.nbContacts; i++)
        {
                msg = newMessage();
        
                Contact c = adressBook.contacts[i];
                
                msg->timestamp = time_s;
                msg->type = type;
                strcpy(msg->ipSender, adressBook.me.ip);
                strcpy(msg->nameSender, adressBook.me.name);          
                
                msg->size = strlen(message)+1;
                msg->message = malloc(RAWSIZE * sizeof(char));
                memset(msg->message, '\0', RAWSIZE);
                strcpy(msg->message, message);
                
                if(type == CONNECTION || c.connected)
                {
                        // Contact name
                        strcpy(msg->nameReceiver, c.name);
                
                        // Contact ip
                        strcpy(msg->ipReceiver, c.ip);
                
                        send_message(msg); 
                }
        }
        
        sleep(1);
        
}

int send_message(Message * msg)
{       
        pthread_t id;
        pthread_create (&id, NULL, send_message_thread,(void *)msg);
        
        return 0;
}

void printMessage(Message msg, char * truc)
{
        printf("%s\nMessage :\n",truc);
        printf("\t timestamp : %d\n",msg.timestamp);
        printf("\t type : %d\n",msg.type);
        printf("\t ipSender : %s\n",msg.ipSender);
        printf("\t ipReceiver : %s\n",msg.ipReceiver);
        printf("\t nameSender : %s\n",msg.nameSender);
        printf("\t nameReceiver : %s\n",msg.nameReceiver);
        printf("\t size : %d\n",msg.size);
        printf("\t message : %s\n",msg.message);
}

void* send_message_thread(void* arg)
{
        Message* msg = (Message*) arg;

        enum clnt_stat stats;
        
        int result;
        
        stats = callrpc(msg->ipReceiver,                       // Contact IP
                       PROGNUM, VERSNUM, PROCNUM,              // Procedure
                       (xdrproc_t) xdr_message, (char *) msg,  // out: Message
                       (xdrproc_t) xdr_int, (char *) &result); // in : int
                
        if (stats != RPC_SUCCESS && msg->type==STANDARD)
        {
                printf("\n\n* The message \"%s\" wasn't sent to %s (receiver had quit)\n\n> ",msg->message,msg->nameReceiver);
                fflush(stdout);    
                deconnectionContact(msg->nameReceiver);
        }
        
        if (result == METOO)
        {
                connectionContact(msg->nameReceiver);
                printf("\n* %s is connected.\n", msg->nameReceiver);
                fflush(stdout);   
        }
        
        free(msg);
        
        return NULL;
}

void send_message_group(int groupIndex, char* message)
{
				int i,j, isAlone=1;
        Message *msg;
				struct timeval tv;
        gettimeofday(&tv,NULL);
        
        for (j=0; j<adressBook.groups[groupIndex].nbMembers; j++)
        {
        				i = searchContactIndex(adressBook.groups[groupIndex].members[j]);
        				Contact c = adressBook.contacts[i];
        				
        				// Formulation du message
								msg = newMessage();
								
								
								msg->timestamp = tv.tv_sec;
								/* Message type */
								msg->type = STANDARD;
								/* Sender IP */
								strcpy(msg->ipSender, adressBook.me.ip);
								/* Sender name */
								strcpy(msg->nameSender, adressBook.me.name);
								
								/* Message contents */
								msg->size = strlen(message)+1;
								msg->message = malloc(sizeof(char) * RAWSIZE);
								memset(msg->message, '\0', RAWSIZE);
								strcpy(msg->message, message);
        				
        				if(c.connected)
								{
								    // Contact name
								    strcpy(msg->nameReceiver, c.name);

								    // Contact ip
								    strcpy(msg->ipReceiver, c.ip);

								    send_message(msg);
								    
								    isAlone =0;
								}
        }        
        
        if(isAlone)
        {
        		printf("\n\n* No contacts connected in your group %s.\n\n> ", adressBook.groups[groupIndex].groupName);
            fflush(stdout);   
       	}
}

